#!/bin/bash
 #=================== SYSTEM ===================#
  SYSTEMD="/etc/systemd/system"
  INITD="/etc/init.d"
  ETCDEF="/etc/default"
  DATABK="/home/print3D/printer_data"
  #清华
  PIP3YUAN="https://pypi.tuna.tsinghua.edu.cn/simple/"
  #阿里
  #PIP3YUAN="http://mirrors.aliyun.com/pypi/simple/"
  #中国科技大学
  #PIP3YUAN="https://pypi.mirrors.ustc.edu.cn/simple/"
  #华中科技大学
  #PIP3YUAN="http://pypi.hustunique.com/simple/"
  #上海交通大学
  #PIP3YUAN="https://mirror.sjtu.edu.cn/pypi/web/simple/"
  #豆瓣
  #PIP3YUAN="http://pypi.douban.com/simple/"
  #百度
  #PIP3YUAN="https://mirror.baidu.com/pypi/simple"
  #搜狐
  #PIP3YUAN="http://mirrors.sohu.com/Python/"
  #=================== KIAUH ==================#
### sourcing all additional scripts
  KIAUH_SRCDIR="/home/print3D/kiauh"
  KIAUH_REPO="https://gitee.com/miroky/kiauh.git"
  green=$(echo -en "\e[92m")
  yellow=$(echo -en "\e[93m")
  magenta=$(echo -en "\e[35m")
  red=$(echo -en "\e[91m")
  cyan=$(echo -en "\e[96m")
  white=$(echo -en "\e[39m")
  home1="/home/print3D"
  INI_FILE="/home/print3D/kiauh.ini"
  LOGFILE="/tmp/kiauh.log"
  RESOURCES="${KIAUH_SRCDIR}/resources"
  BACKUP_DIR="/home/print3D/kiauh-backups"
  #=====================PIP======================#
  # for using official pip source, comment next line
  PIP_MIRROR="https://pypi.tuna.tsinghua.edu.cn/simple"
  #================== KLIPPER ===================#
  KLIPPY_ENV="/home/print3D/klippy-env"
  KLIPPER_DIR="/home/print3D/klipper"
  KLIPPER_REPO="https://gitee.com/miroky/klipper.git"
  KLIPPER_BJ="virtualenv python3-dev libffi-dev build-essential libncurses-dev libusb-dev avrdude gcc-avr binutils-avr avr-libc stm32flash  gcc-arm-none-eabi  libusb-1.0 pkg-config dfu-util binutils-arm-none-eabi"
  #libnewlib-arm-none-eabi
  KLIPPER_TXT="/home/print3D/klipper/scripts/klippy-requirements.txt"
  #================= MOONRAKER ==================#
  MOONRAKER_ENV="/home/print3D/moonraker-env"
  MOONRAKER_DIR="/home/print3D/moonraker"
  MOONRAKER_REPO="https://gitee.com/miroky/moonraker.git"
  MOONRAKER_TXT="/home/print3D/moonraker/scripts/moonraker-requirements.txt"
  #================= PolicyKit ==================#
  POLKIT_LEGACY_DIR="/etc/polkit-1/localauthority/50-local.d"
  POLKIT_DIR="/etc/polkit-1/rules.d"
  POLKIT_USR_DIR="/usr/share/polkit-1/rules.d"
  MOONRAKER_UNIT="/etc/init.d/moonraker"
  MOONRAKER_GID="-1"
  #================= MAINSAIL ===================#
  MAINSAIL_DIR="/home/print3D/mainsail"
  MAINSAIL_REPO_API="https://gitee.com/Neko-vecter/mainsail-releases/raw/main/mainsail-res"
  MAINSAIL_TAGS="https://gitee.com/Neko-vecter/mainsail-releases/raw/main/Neko-mainsail-res"
  MAINSAIL_MACRO="https://gitee.com/Neko-vecter/mainsail-releases/raw/main/klipper_config/mainsail.cfg"
  #================== FLUIDD ====================#
  FLUIDD_DIR="/home/print3D/fluidd"
  FLUIDD_REPO_API="https://gitee.com/Neko-vecter/fluidd-releases/raw/main/fluidd-res"
  FLUIDD_TAGS="https://gitee.com/Neko-vecter/fluidd-releases/raw/main/Neko-fluidd-res"
  FLUIDD_MACRO="https://gitee.com/Neko-vecter/fluidd-releases/raw/main/klipper_config/fluidd.cfg"
  NGINX_SA="/etc/nginx/sites-available"
  NGINX_SE="/etc/nginx/sites-enabled"
  NGINX_CONFD="/etc/nginx/conf.d"
  #=============== KLIPPERSCREEN ================#
  KLIPPERSCREEN_ENV="/home/print3D/KlipperScreen-env"
  KLIPPERSCREEN_DIR="/home/print3D/KlipperScreen"
  KLIPPERSCREEN_REPO="https://gitee.com/Neko-vecter/KlipperScreen.git"
  KLIPPERSCREEN_TXT="/home/print3D/KlipperScreen/scripts/KlipperScreen-requirements.txt"
  XSERVER="xinit xinput x11-xserver-utils xserver-xorg-input-evdev xserver-xorg-input-libinput libgirepository1.0-dev gcc libcairo2-dev pkg-config python3-dev gir1.2-gtk-3.0 librsvg2-common libopenjp2-7 libatlas-base-dev wireless-tools libdbus-glib-1-dev autoconf xserver-xorg-legacy fonts-wqy-zenhei libmpv-dev "
#libmpv-dev
Red='\033[0;31m'
Green='\033[0;32m'
Cyan='\033[0;36m'
Normal='\033[0m'
#=================================================#
#================ INSTALL KIAUH ================#
#=================================================#
function clone_kiauh() {
    local dep
   dep=(git wget curl unzip dfu-util virtualenv)
  ### 检查依赖项
  dependency_check "${dep[@]}"
  [[ -d ${KIAUH_SRCDIR} ]] && rm -rf "${KIAUH_SRCDIR}"
if sudo git clone ${KIAUH_REPO} ${KIAUH_SRCDIR}; then
    status_msg  "KIAUH成功！"
  else
   sleep 2s
   [[ -d ${KIAUH_SRCDIR} ]] && rm -rf "${KIAUH_SRCDIR}"
   if sudo git clone ${KIAUH_REPO} ${KIAUH_SRCDIR}; then
     status_msg "KIAUH成功！"
   else
     error_msg  "KIAUH失败！"
   fi
 fi
}
#=================================================#
#================ INSTALL KLIPPER ================#
#=================================================#

function run_klipper_setup() {
   local dep
   dep=(git wget curl unzip dfu-util virtualenv)
  ### 检查依赖项
  dependency_check "${dep[@]}"
  ### step 1:克隆klipper
  clone_klipper
  ### step 2: 安装klipper依赖项并创建python-virtualenv
  install_klipper_packages
  create_virtualenv "${KLIPPY_ENV}" "${KLIPPER_TXT}"
  ### step 3: 创建klipper实例
  create_required_folders "${DATABK}"
  create_klipper_service "printer"
  ### step 4: 启用并启动所有实例
  install_config_klipper
  install_script_klipper
  #start_software_klipper
  status_msg "klipper安装完成！"
}
function clone_klipper() {
  local repo="${KLIPPER_REPO}"
  local branch="master"
  if [[ ${repo} =~ .*"github.com".* ]] || [[ ! ${repo} =~ ^"http".* ]]; then
    repo=$(echo "${repo}" | sed -r "s/^(http|https):\/\/github\.com\///i; s/\.git$//")
    repo="https://github.com/${repo}"
  fi
  ### 强制删除现有的klipper目录并克隆到新的klippr目录
  [[ -d ${KLIPPER_DIR} ]] && rm -rf "${KLIPPER_DIR}"

  status_msg "从${repo}克隆Klipper ..."
  if sudo git clone "${repo}" "${KLIPPER_DIR}"; then
    cd "${KLIPPER_DIR}" && git checkout "${branch}"
  else
    sleep 2s
    [[ -d ${KLIPPER_DIR} ]] && rm -rf "${KLIPPER_DIR}"
    sudo git clone "${repo}" "${KLIPPER_DIR}"
  fi
}

function install_klipper_packages() {
  ### 更新系统包信息
    if ! sudo apt-get update --allow-releaseinfo-change; then
      log_error "更新程序包列表时失败"
      error_msg "更新程序包列表失败!"
    fi
    ### 安装所需的程序包
    status_msg "正在安装所需的程序包..."
    if ! sudo apt-get install --yes ${KLIPPER_BJ}; then
       sleep 2s
       sudo dpkg --configure -a
       if ! sudo apt-get install --yes  ${KLIPPER_BJ}; then
           log_error "安装所需的klipper程序包时失败"
           error_msg "安装所需的程序包失败!"
        else
            ok_msg "已安装所需的程序包!"
       fi
     else
           ok_msg "已安装所需的程序包!"
        
    fi

}
# Step 5:启动主机软件
function write_example_printer_cfg() {
  local cfg=${1}
  local cfg_template="${KIAUH_SRCDIR}/resources/example.printer.cfg"
  status_msg "创建最小示例printer.cfg ..."
  if  cp "${cfg_template}" "${cfg}"; then
    ok_msg "创建的最小示例printer.cfg!"
  else
    error_msg "无法创建最小示例printer.cfg!"
  fi
}
function create_required_folders() {
  local printer_data=${1} folders
  folders=("backup" "certs" "config" "database" "gcodes" "comms" "logs" "systemd")
  for folder in "${folders[@]}"; do
    local dir="${printer_data}/${folder}"

    ### 删除moonraker可能创建的符号链接
    if [[ -L "${dir}" && -d "${dir}" ]]; then
      rm "${dir}"
    fi

    if [[ ! -d "${dir}" ]]; then
      status_msg "正在创建文件夹 '${dir}' ..."
      mkdir -p "${dir}"
      ok_msg "已创建文件夹 '${dir}' !"
    fi
  done
}
function create_klipper_service() {
  local instance_name=${1}

  local printer_data
  local cfg_dir
  local cfg
  local log
  local klippy_serial
  local klippy_socket
  local env_file
  local service
  local service_template
  local env_template
  local suffix

  printer_data="/home/print3D/${instance_name}_data"
  cfg_dir="${printer_data}/config"
  cfg="${cfg_dir}/printer.cfg"
  log="${printer_data}/logs/klippy.log"
  klippy_serial="${printer_data}/comms/klippy.serial"
  klippy_socket="${printer_data}/comms/klippy_uds"
  env_file="${printer_data}/systemd/klipper.env"

  if [[ ${instance_name} == "printer" ]]; then
    suffix="${instance_name//printer/}"
  else
    suffix="-${instance_name//printer_/}"
  fi

  create_required_folders "${printer_data}"

  service_template="${KIAUH_SRCDIR}/resources/klipper.service"
  env_template="${KIAUH_SRCDIR}/resources/klipper.env"
  service="${SYSTEMD}/klipper${suffix}.service"

  if [[ ! -f ${service} ]]; then
    status_msg "创建Klipper服务文件 ..."

    sudo cp "${service_template}" "${service}"
    sudo cp "${env_template}" "${env_file}"
    sudo sed -i "s|%USER%|${USER}|g; s|%ENV%|${KLIPPY_ENV}|; s|%ENV_FILE%|${env_file}|" "${service}"
    sudo sed -i "s|%USER%|${USER}|; s|%LOG%|${log}|; s|%CFG%|${cfg}|; s|%PRINTER%|${klippy_serial}|; s|%UDS%|${klippy_socket}|" "${env_file}"

    ok_msg "Klipper服务文件已创建!"
  fi

  if [[ ! -f ${cfg} ]]; then
    write_example_printer_cfg "${cfg}"
  fi
}
function install_config_klipper(){
    DEFAULTS_FILE=/etc/default/klipper
        mkdir -p /etc/default
        status_msg  "正在安装系统启动配置..."
        cat > ${DEFAULTS_FILE} <<EOF
KLIPPER_USER="print3D"
KLIPPY_CONFIG="/home/print3D/printer_data/config/printer.cfg"
KLIPPY_LOG="/home/print3D/printer_data/logs/klippy.log"
KLIPPY_SOCKET="/home/print3D/printer_data/comms/klippy_uds"
KLIPPY_SERIAL="/home/print3D/printer_data/comms/klippy.serial"
KLIPPY_PRINTER="/tmp/printer"
KLIPPY_EXEC="/home/print3D/klippy-env/bin/python"
KLIPPY_ARGS="/home/print3D/klipper/klippy/klippy.py \$KLIPPY_CONFIG -I \$KLIPPY_SERIAL -l \$KLIPPY_LOG -a \$KLIPPY_SOCKET"
EOF
}
function install_script_klipper(){
    status_msg "正在安装系统启动脚本..."
    cp "${KIAUH_SRCDIR}/resources/klipper.env" "${DATABK}/systemd/klipper.env"
    sed -i "s|%USER%|print3D|; s|%PRINTER_DATA%|${DATABK}|" "${DATABK}/systemd/klipper.env"
  
    chmod +x /etc/init.d/klipper
    chmod 777 /etc/init.d/klipper
    #rc-update add klipper defaults 80 20
}
#=================================================#
#================ INSTALL MOONRAKER ================#
#=================================================#
function moonraker_setup() {
  local dep=(git wget curl unzip dfu-util virtualenv)
  dep+=(libjpeg-dev zlib1g-dev)
  dependency_check "${dep[@]}"
  local instance_arr="print3D"
  ### step 1: 克隆 moonraker
  clone_moonraker
  ### step 2: 安装moonraker依赖项并创建python-virtualenv
  status_msg "正在安装依赖项 ..."
  install_moonraker_dependencies
  create_virtualenv "${MOONRAKER_ENV}" "${MOONRAKER_TXT}"
  ### step 4: 创建moonraker实例
  configure_moonraker_service
  ### step 6: 启用并启动所有实例
  install_config_moonraker
  install_script_moonraker
  status_msg "moonraker安装完成！"
}
function install_moonraker_dependencies() {
  local packages
    local install_script="${MOONRAKER_DIR}/scripts/install-moonraker.sh"

    ### 从官方安装脚本中读取PKGLIST
    status_msg "正在读取依赖项..."
    # shellcheck disable=SC2016
    packages="$(grep "PKGLIST=" "${install_script}" | cut -d'"' -f2 | sed 's/\${PKGLIST}//g' | tr -d '\n')"

    echo "${cyan}${packages}${white}" | tr '[:space:]' '\n'
    read -r -a packages <<< "${packages}"

    ### 更新系统包信息
    status_msg "正在更新程序包列表..."
    if ! sudo apt-get update --allow-releaseinfo-change; then
      log_error "更新程序包列表时失败"
      error_msg "更新程序包列表失败!"
      
    fi

    ### 安装所需的程序包
    status_msg "正在安装所需的程序包..."
    if ! sudo apt-get install --yes "${packages[@]}"; then
      sleep 2s
      sudo dpkg --configure -a
      if ! sudo apt-get install --yes "${packages[@]}"; then
          log_error "安装所需的moonraker包时出现故障"
          error_msg "安装所需的程序包失败!"
      else
            ok_msg "已安装所需的程序包!"
      fi
    else
         ok_msg "已安装所需的程序包!"
    fi
sleep 2s
       sudo dpkg --configure -a
}

function clone_moonraker() {
  status_msg "从克隆Moonraker ${repo} ..."
  ### 强制删除现有的moonraker目录并克隆到新的moonroker目录
  [[ -d ${MOONRAKER_DIR} ]] && rm -rf "${MOONRAKER_DIR}"
  if ! sudo git clone "${MOONRAKER_REPO}" "${MOONRAKER_DIR}"; then
    sleep 2s
    [[ -d ${MOONRAKER_DIR} ]] && rm -rf "${MOONRAKER_DIR}"
    sudo git clone "${MOONRAKER_REPO}" "${MOONRAKER_DIR}"
  fi
  sed -i "s/self.full_access_roots.clear()/self.full_access_roots/" /home/print3D/moonraker/moonraker/components/file_manager/file_manager.py
  #sed -i -e '/DBus Connection Not available, systemd/{n;d}' -e '$!N;/\n.*DBus Connection Not available, systemd/!P;D'  /home/print3D/moonraker/moonraker/components/machine.py
  #sed -i -e '/DBus Connection Not available, systemd/d'  /home/print3D/moonraker/moonraker/components/machine.py
}

function write_moonraker_conf() {
  local cfg_dir=${1} cfg=${2} port=${3} uds=${4} lan=${5}  
  local conf_template="${KIAUH_SRCDIR}/resources/moonraker.conf"
  [[ ! -d ${cfg_dir} ]] && mkdir -p "${cfg_dir}"
  if [[ ! -f ${cfg} ]]; then
    status_msg "在中创建moonraker.conf ${cfg_dir} ..."
    cp "${conf_template}" "${cfg}"
    sed -i "s|%USER%|${USER}|g; s|%PORT%|${port}|; s|%UDS%|${uds}|" "${cfg}"
    #如果主机ip不在默认ip范围内，则替换占位符，
    #否则，从配置中删除占位符
    if ! grep -q "${lan}" "${cfg}"; then
      sed -i "s|%LAN%|${lan}|" "${cfg}"
    else
      sed -i "/%LAN%/d" "${cfg}"
    fi
    ok_msg "moonraker.conf已创建!"
  else
     status_msg "文件 '${cfg_dir}/moonraker.conf已经存在！ \n跳过..."
  fi
    
}

function configure_moonraker_service() {
  local printer_data cfg_dir service env_file
    i=""
    printer_data="/home/print3D/printer_data"
    cfg_dir="${printer_data}/config"
    service="${SYSTEMD}/moonraker.service"
    env_file="${printer_data}/systemd/moonraker.env"

    ### 创建所需的文件夹结构
    create_required_folders "${printer_data}"

    ### 写入单实例服务
    write_moonraker_service "" "${printer_data}" "${service}" "${env_file}"
    ok_msg "Moonraker已创建实例!"


}
function write_moonraker_service() {
  local i=${1} printer_data=${2} service=${3} env_file=${4}
  local service_template="${KIAUH_SRCDIR}/resources/moonraker.service"
  local env_template="${KIAUH_SRCDIR}/resources/moonraker.env"
  local MOONRAKER_CONFIG="/home/print3D/printer_data/config/moonraker.conf"
  local MOONRAKER_LOG="/home/print3D/printer_data/logs/moonraker.log"
  printer_data="${printer_data} -c ${MOONRAKER_CONFIG} -l ${MOONRAKER_LOG} "
  ### 替换所有占位符
  if [[ ! -f ${service} ]]; then
    status_msg "创建Moonraker服务 ${i} ..."
    sudo cp "${service_template}" "${service}"
    sudo cp "${env_template}" "${env_file}"

    [[ -z ${i} ]] && sudo sed -i "s| %INST%||" "${service}"
    [[ -n ${i} ]] && sudo sed -i "s|%INST%|${i}|" "${service}"
    sudo sed -i "s|%USER%|${USER}|g; s|%ENV%|${MOONRAKER_ENV}|; s|%ENV_FILE%|${env_file}|" "${service}"
    sudo sed -i "s|%USER%|${USER}|; s|%PRINTER_DATA%|${printer_data}|" "${env_file}"
  fi
}
function moonraker_systemd() {
  local services
  local blacklist
  local ignore
  local match

  ###
  #任何以自己的名义使用“月球客”的月球客客户都必须使用
  #该变量，否则它们将被错误地识别为月球探测器实例
  blacklist="obico"

  ignore="${SYSTEMD}/moonraker-(${blacklist}).service"
  match="${SYSTEMD}/moonraker(-[0-9a-zA-Z]+)?.service"

  services=$(find "${SYSTEMD}" -maxdepth 1 -regextype awk ! -regex "${ignore}" -regex "${match}" | sort)
  echo "${services}"
}
function install_config_moonraker(){
  chmod -R 777 ${DATABK}
  chmod -R 777 ${DATABK}
    DEFAULTS_FILE=/etc/default/moonraker
        status_msg  "正在安装系统启动配置..."
        cat > ${DEFAULTS_FILE} <<EOF
KLIPPER_USER="print3D"
MOONRAKER_DATA="/home/print3D/printer_data"
MOONRAKER_CONFIG="/home/print3D/printer_data/config/moonraker.conf"
MOONRAKER_LOG="/home/print3D/printer_data/logs/moonraker.log"
MOONRAKER_SOCKET="/tmp/moonraker_uds"
MOONRAKER_PRINTER="/tmp/printer"
MOONRAKER_EXEC="/home/print3D/moonraker-env/bin/python"
MOONRAKER_ARGS="/home/print3D/moonraker/moonraker/moonraker.py -c \$MOONRAKER_CONFIG -l \$MOONRAKER_LOG -d \$MOONRAKER_DATA"
EOF
}
function install_script_moonraker(){
    status_msg "正在安装系统启动脚本..."
    sudo cp "${KIAUH_SRCDIR}/resources/moonraker.env" "${DATABK}/systemd/moonraker.env"
    sudo sed -i "s|%USER%|print3D|; s|%PRINTER_DATA%|${DATABK}|" "${DATABK}/systemd/moonraker.env"
    chmod +x /etc/init.d/moonraker
    chmod 777 /etc/init.d/moonraker
 
}
#===================================================#
#================== INSTALL FLUIDD =================#
#===================================================#
function install_fluidd() {

   ### 检查依赖项
  local dep=(wget nginx)
  dependency_check "${dep[@]}"
  ### 检测冲突的Haproxy和Apache2安装
  status_msg "正在初始化Fluidd安装 ..."
  mkdir -p /etc/nginx/conf.d
  mkdir -p /etc/nginx/sites-available
  mkdir -p /etc/nginx/sites-enabled
  sed -i 's/user www-data;/\#user www-data;/' /etc/nginx/nginx.conf
  sed -i '/\/etc\/nginx\/http.d\/\*.conf;/a\        include \/etc\/nginx\/sites-enabled\/\*;'  /etc/nginx/nginx.conf
  sed -i "/http {/a\map \$http_upgrade \$connection_upgrade {\n    default upgrade;\n    ''      close;\n   }"  /etc/nginx/nginx.conf
  sed -i 's/http.d/conf.d/g' /etc/nginx/nginx.conf
  ### 下载fluidd
  download_fluidd
  ### 创造 /etc/nginx/conf.d/upstreams.conf
  set_upstream_nginx_cfg
  ### 创造 /etc/nginx/sites-available/<interface config>
  set_nginx_cfg "fluidd"
  ### ubuntu 21及以上版本上的nginx需要特殊权限才能访问这些文件
  set_nginx_permissions
  ### 符号链接nginx日志
  symlink_webui_nginx_log "fluidd"
  ### 要求用户安装推荐的Web界面宏
  download_fluidd_macros
  ### 确认消息
  print_confirm "Fluidd已设置!"
}
function download_fluidd() {
  local url
  url=$(get_fluidd_download_url)

  status_msg "正在${url}从下载Fluidd  ..."

  if [[ -d ${FLUIDD_DIR} ]]; then
    rm -rf "${FLUIDD_DIR}"
  fi

  mkdir "${FLUIDD_DIR}" && cd "${FLUIDD_DIR}"

  if wget "${url}"; then
    ok_msg "下载完成!"
    status_msg "正在提取存档 ..."
    unzip -q -o ./*.zip && ok_msg "Done!"
    status_msg "删除下载的存档 ..."
    rm -rf ./*.zip && ok_msg "Done!"
  else
    print_error "下载 Fluidd from\n ${url}\n failed!"
    
  fi
}
function get_fluidd_download_url() {
  local tags latest_tag latest_url stable_tag stable_url url
  tags=$(curl -s "${FLUIDD_TAGS}" | grep "name" | cut -d'"' -f4)
  download_url=$(curl -s "${FLUIDD_TAGS}" | grep "download_url" | cut -d'"' -f4)
  # 获取最新标签和url
  latest_tag=$(echo "${tags}" | head -1)
  latest_url=$(echo "${download_url}" | head -1)
  url="${latest_url}"
  echo "${url}"
}
function set_upstream_nginx_cfg() {
  local upstreams="${NGINX_CONFD}/upstreams.conf"
  local common_vars="${NGINX_CONFD}/common_vars.conf"
  ### 将nginx配置复制到目标目标
  [[ ! -f ${upstreams} ]] &&  cp "${RESOURCES}/upstreams.conf" "${upstreams}"
  [[ ! -f ${common_vars} ]] &&  cp "${RESOURCES}/common_vars.conf" "${common_vars}"
}
function set_nginx_cfg() {
  local interface=${1}
    #检查相关性
    local cfg_src="${RESOURCES}/${interface}"
    local cfg_dest="/etc/nginx/sites-available/${interface}"
    status_msg "正在为创建NGINX配置 ${interface^} ..."
    # 将配置复制到目标并设置正确的用户名
    [[ -f ${cfg_dest} ]] &&  rm -rf "${cfg_dest}"
    cp "${cfg_src}" "${cfg_dest}"
    sed -i "/root/s/pi/print3D/" "${cfg_dest}"
    if [[ ${interface} == "fluidd" ]]; then
       sed -i "s/listen\s[0-9]*;/listen 8080;/" "${cfg_dest}"
       sed -i "s/listen\s\[\:*\]\:[0-9]*;/listen \[::\]\:8080;/" "${cfg_dest}"
       sed -i 's/http:\/\/apiserver/http:\/\/127.0.0.1:7125/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer1/127.0.0.1:8080/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer2/127.0.0.1:8081/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer3/127.0.0.1:8082/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer4/127.0.0.1:8083/g' "${cfg_dest}"
       ok_msg "${interface^} 为端口配置 8080!"
    else
       sed -i "s/listen\s[0-9]*;/listen 8081;/" "${cfg_dest}"
       sed -i "s/listen\s\[\:*\]\:[0-9]*;/listen \[::\]\:8081;/" "${cfg_dest}"
       sed -i 's/http:\/\/apiserver/http:\/\/127.0.0.1:7125/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer1/127.0.0.1:8080/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer2/127.0.0.1:8081/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer3/127.0.0.1:8082/g' "${cfg_dest}"
       sed -i 's/mjpgstreamer4/127.0.0.1:8083/g' "${cfg_dest}"
       ok_msg "${interface^} 为端口配置 8081!"
    fi
    #删除nginx默认配置
    if [[ -e "/etc/nginx/sites-enabled/default" ]]; then
      rm "/etc/nginx/sites-enabled/default"
    fi

    #为自己的站点创建符号链接
    if [[ ! -e "/etc/nginx/sites-enabled/${interface}" ]]; then
       ln -s "/etc/nginx/sites-available/${interface}" "/etc/nginx/sites-enabled/"
    fi
    ok_msg "NGINX 的配置 ${interface^} 已设置!"

}
function set_nginx_permissions() {
  local homedir_perm
  local exec_perms_count
  homedir_perm=$(ls -ld "${home}/home/print3D")
  exec_perms_count=$(echo "${homedir_perm}" | cut -d" " -f1 | grep -c "x")
  if (( exec_perms_count < 3 )); then
    status_msg "授予NGINX所需的权限 ..."
    chmod og+x "${home}/home/print3D" && ok_msg "Done!"
  fi
  return
}
function symlink_webui_nginx_log() {
  local interface path access_log error_log regex logpaths
  interface=${1}
  access_log="/var/log/nginx/${interface}-access.log"
  error_log="/var/log/nginx/${interface}-error.log"
  path="${DATABK}/log"
    [[ ! -d ${path} ]] && mkdir -p "${path}"
    if [[ -f ${access_log} && ! -L "${path}/${interface}-access.log" ]]; then
      status_msg "正在为 ${access_log}创建链接 ..."
      ln -s "${access_log}" "${path}"
      ok_msg "Symlink已创建: ${path}/${interface}-access.log"
    fi
    if [[ -f ${error_log} && ! -L "${path}/${interface}-error.log" ]]; then
      status_msg "正在为  ${error_log}创建链接 ..."
      ln -s "${error_log}" "${path}"
      ok_msg "Symlink已创建: ${path}/${interface}-error.log"
    fi

}
function download_fluidd_macros() {
  local path=${DATABK}/config
  status_msg "克隆fluidd配置 ..."
  wget ${FLUIDD_MACRO} -P "${path}";
  #patch_fluidd_update_manager
  ok_msg "Done!"
}
function patch_fluidd_update_manager() {
 local fluidd_cfg path line gcode_dir conf
 path=${DATABK}/config 
 conf="${DATABK}/config/moonraker.conf"
    if ! grep -Eq "^\[include fluidd.cfg\]$" "${path}/printer.cfg"; then
       log_info "${path}/printer.cfg"
       sed -i "1 i [include fluidd.cfg]" "${path}/printer.cfg"
       sed -i "/serial:/c serial: /dev/ttyOcto4a \n \#baud: 115200 \#\(非必须，默认波特率连不上可改为115200\) " "${path}/printer.cfg"
    fi
    line="$(($(grep -n "\[include fluidd.cfg\]" "${path}/printer.cfg" | tail -1 | cut -d: -f1) + 1))"
    gcode_dir="${DATABK}/gcodes"
    if ! grep -Eq "^\[virtual_sdcard\]$" "${path}/fluidd.cfg"; then
       log_info "${path}/fluidd.cfg"
       sed -i "${line} i \[virtual_sdcard]\n path: ${gcode_dir}\n on_error_gcode: CANCEL_PRINT\n" "${path}/fluidd.cfg"
    fi

    if ! grep -Eq "^\[update_manager fluidd\]\s*$" "${conf}"; then
      ### add new line to conf if it doesn't end with one
      [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}"
      ### add Fluidds update manager section to moonraker.conf
      status_msg "将Fluidd添加到文件中的更新管理器:\n ${conf}"
      /bin/sh -c "cat >> ${conf}" << MOONRAKER_CONF

[update_manager fluidd]
type: web
channel: stable
repo: fluidd-core/fluidd
path: /home/print3D/fluidd
MOONRAKER_CONF

    fi
}
function install_script_nginx(){
    
    chmod +x /etc/init.d/nginxk
    chmod 777 /etc/init.d/nginxk
}
#===================================================#
#================= INSTALL MAINSAIL ================#
#===================================================#
function install_mainsail() {
  status_msg "正在初始化mainsail安装 ..."
  download_mainsail
  set_nginx_cfg "mainsail"
  symlink_webui_nginx_log "mainsail"
  download_mainsail_macros
  install_script_nginx
  print_confirm "mainsail已设置!"
}
function download_mainsail() {
  local url
  url=$(get_mainsail_download_url)
  status_msg "正在从 ${url} ..."
  if [[ -d ${MAINSAIL_DIR} ]]; then
    rm -rf "${MAINSAIL_DIR}"
  fi
  mkdir "${MAINSAIL_DIR}" && cd "${MAINSAIL_DIR}"

  if wget "${url}"; then
    ok_msg "下载完成!"
    status_msg "Extracting archive ..."
    unzip -q -o ./*.zip && ok_msg "Done!"
    status_msg "正在提取存档 ..."
    rm -rf ./*.zip && ok_msg "Done!"
  else
    print_error "正在从\n ${url}\n 失败!"
    
  fi
}
function get_mainsail_download_url() {
  local ms_tags tags latest_tag latest_url stable_tag stable_url url
  tags=$(curl -s "${MAINSAIL_TAGS}" | grep "name" | cut -d'"' -f4)
  download_url=$(curl -s "${MAINSAIL_TAGS}" | grep "download_url" | cut -d'"' -f4)
  # 获取最新标签和url
  latest_tag=$(echo "${tags}" | head -1)
  latest_url=$(echo "${download_url}" | head -1)
  url="${latest_url}"
  echo "${url}"
}
function download_mainsail_macros() {
  local path="${DATABK}/config"
  status_msg "克隆 mainsail配置 ..."
  wget ${MAINSAIL_MACRO} -P "${path}";
  #patch_mainsail_update_manager
  ok_msg "Done!"
}
function patch_mainsail_update_manager() {
  local ms_cfg_repo path  line gcode_dir conf
  path="${DATABK}/config"
  conf="${DATABK}/config/moonraker.conf"
  if ! grep -Eq "^\[include mainsail.cfg\]$" "${path}/printer.cfg"; then
    log_info "${path}/printer.cfg"
    sed -i "1 i [include mainsail.cfg]" "${path}/printer.cfg"
  fi
  line="$(($(grep -n "\[include mainsail.cfg\]" "${path}/printer.cfg" | tail -1 | cut -d: -f1) + 1))"
  gcode_dir="${DATABK}/gcodes"
  if ! grep -Eq "^\[virtual_sdcard\]$" "${path}/mainsail.cfg"; then
      log_info "${path}/mainsail.cfg"
      sed -i "${line} i \[virtual_sdcard]\n path: ${gcode_dir}\n on_error_gcode: CANCEL_PRINT\n" "${path}/mainsail.cfg"
  fi
  if ! grep -Eq "^\[update_manager mainsail\]\s*$" "${conf}"; then
    ### add new line to conf if it doesn't end with one
    [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}"
    ### add Mainsails update manager section to moonraker.conf
    status_msg "将Mainsail添加到文件中的更新管理器:\n       ${conf}"
    /bin/sh -c "cat >> ${conf}" << MOONRAKER_CONF

[update_manager mainsail]
type: web
channel: stable
repo: mainsail-crew/mainsail
path: /home/print3D/mainsail
MOONRAKER_CONF
    fi
}
#===================================================#
#============== INSTALL KLIPPERSCREEN ==============#
#===================================================#
function klipperscreen_setup() {
  # 强制删除现有KlipperScreen目录
  [[ -d ${KLIPPERSCREEN_DIR} ]] && rm -rf "${KLIPPERSCREEN_DIR}"
  # 克隆到新的KlipperScreen目录
  if ! git clone "${KLIPPERSCREEN_REPO}" "${KLIPPERSCREEN_DIR}"; then
    print_error "克隆KlipperScreen从\n ${KLIPPERSCREEN_REPO}\n 失败!"
  fi
  status_msg "安装环境 ..."
  install_packages
  create_virtualenv "${KLIPPERSCREEN_ENV}" "${KLIPPERSCREEN_TXT}"
  modify_user
  update_x11
  install_config_KlipperScreen
  add_desktop_file
  install_systemd_service
  status_msg "KlipperScreen安装完成!"
}
function modify_user(){
  
  sudo gpasswd --add print3D dialout
  sudo gpasswd --add print3D sudo
  sudo gpasswd --add print3D tty
  sudo gpasswd --add print3D root
}
function update_x11(){
    if [ -e /etc/X11/Xwrapper.config ]
    then
       
        sed -i 's/allowed_users=console/allowed_users=anybody/g' /etc/X11/Xwrapper.config
    else
        
        echo 'allowed_users=anybody' |  tee /etc/X11/Xwrapper.config
    fi
}
function add_desktop_file(){
    DESKTOP=$(<$KLIPPERSCREEN_DIR/scripts/KlipperScreen.desktop)
    mkdir -p $HOME/.local/share/applications/
    echo "$DESKTOP" | tee $HOME/.local/share/applications/KlipperScreen.desktop > /dev/null
}
function install_config_KlipperScreen(){
    DEFAULTS_FILE=/etc/default/KlipperScreen
        status_msg  "正在安装启动配置..."
        cat > ${DEFAULTS_FILE} <<EOF
    # Configuration for /etc/init.d/KlipperScreen
    KS_USER=print3D
    KS_EXEC="/bin/bash"
    KS_ARGS=" /etc/init.d/KlipperScreensh"

EOF
    chmod +x /root/print3D/ksdelay.sh
    chmod +x /etc/init.d/KlipperScreen
    chmod +x /etc/init.d/KlipperScreensh
    chmod 777 /root/print3D/ksdelay.sh
    chmod 777 /etc/init.d/KlipperScreen
    chmod 777 /etc/init.d/KlipperScreensh

}
function install_packages()
{
    sudo apt-get update
    status_msg "安装KlipperScreen依赖项"
    sudo apt-get install -y $XSERVER
    if [ $? -eq 0 ]; then
        ok_msg "KlipperScreen依赖项已安装！"
    else
        sleep 2s
        sudo dpkg --configure -a
        sudo apt-get install -y $XSERVER 
        if [ $? -eq 0 ]; then
           ok_msg "KlipperScreen依赖项已安装！"
        else
           error_msg "KlipperScreen依赖项安装失败！"
        fi
    fi

    sudo service mask ModemManager.service
}
function install_systemd_service()
{
    status_msg "安装KlipperScreen单元文件"
    sudo cp ${KLIPPERSCREEN_DIR}/scripts/KlipperScreen.service  /etc/systemd/system/ 
    sudo sed -i  's/KS_USER/${USER}/g' /etc/systemd/system/KlipperScreen.service
    sudo sed -i  's/Environment/Environment="localhost:0 \/home\/print3D\/KlipperScreen-env\/bin\/python"/g' /etc/systemd/system/KlipperScreen.service
    sudo sed -i  's/ExecStart/ExecStart="\/home\/print3D\/KlipperScreen\/screen.py -c \/home\/print3D\/printer_data\/config\/KlipperScreen.conf"/g' /etc/systemd/system/KlipperScreen.service

}
#===================================================#
#============== INSTALL qd ==============#
#===================================================#
function octoklipper_install(){
  wget https://gitee.com/xiaoh5001/klipperocto4a/raw/master/scripts/KlipperScreen.conf   -O ${DATABK}/config/KlipperScreen.conf &>/dev/null
  wget https://gitee.com/xiaoh5001/klipperocto4a/raw/master/scripts/moonraker.conf  -O ${DATABK}/config/moonraker.conf &>/dev/null
  wget https://gitee.com/xiaoh5001/klipperocto4a/raw/master/scripts/printer.cfg  -O ${DATABK}/config/printer.cfg &>/dev/null 
  [[ -d /root/extensions/KlipperScreen} ]] && rm -rf /root/extensions/KlipperScreen
  mkdir -p /root/extensions/KlipperScreen
}
#================================================#
#============= MESSAGE FORMATTING ===============#
#================================================#
function do_action_service() {
  local services action=${1} service=${2}
  services=$(find "${SYSTEMD}" -maxdepth 1 -regextype posix-extended -regex "${SYSTEMD}/${service}(-[0-9a-zA-Z]+)?.service" | sort)

  if [[ -n ${services} ]]; then
    for service in ${services}; do
      service=$(echo "${service}" | rev | cut -d"/" -f1 | rev)
      status_msg "${action^} ${service} ..."

      if sudo systemctl "${action}" "${service}"; then
        log_info "${service}: ${action} > 成功"
        ok_msg "${action^} ${service} 成功!"
      else
        log_warning "${service}: ${action} > 失败"
        warn_msg "${action^} ${service} 失败!"
      fi
    done
  fi
}
function create_virtualenv() {
  local ljm="${1}"
  local wjm="${2}"
  status_msg "正在安装$（“python3”-V）虚拟环境..."
  [[ -d ${ljm} ]] && rm -rf "${ljm}"
  if virtualenv -p "python3" "${ljm}"; then
    "${ljm}"/bin/pip install -U pip  setuptools -i "${PIP3YUAN}"
    "${ljm}"/bin/pip install -r "${wjm}" -i "${PIP3YUAN}"
  else
    sleep 2s
    sudo dpkg --configure -a
    if virtualenv -p "python3" "${ljm}"; then
        "${ljm}"/bin/pip install -U pip  setuptools -i "${PIP3YUAN}"
        "${ljm}"/bin/pip install -r "${wjm}" -i "${PIP3YUAN}"
    else
        log_error "创建python3环境时失败"
        error_msg "virtualenv创建失败！"
    fi
  fi
}
function dependency_check(){
  local dep=( "${@}" )
  local packages
  status_msg "正在检查以下依赖项:"

  #检查是否安装了程序包，如果没有，请将其名称写入数组
  for pkg in "${dep[@]}"; do
    echo -e "${cyan}● ${pkg} ${white}"
    [[ ! $(dpkg-query -f'${Status}' --show "${pkg}" 2>/dev/null) = *\ installed ]] && \
    packages+=("${pkg}")
  done

  #如果数组不为空，则从数组安装程序包
  if (( ${#packages[@]} > 0 )); then
    status_msg "安装以下依赖项:"
    for package in "${packages[@]}"; do
      echo -e "${cyan}● ${package} ${white}"
    done
    echo

    if sudo apt-get update --allow-releaseinfo-change && sudo apt-get install "${packages[@]}" -y; then
      ok_msg "已安装依赖项!"
    else
      error_msg "安装依赖项失败!"
      return 1 # exit kiauh
    fi
  else
    ok_msg "已满足依赖项!"
    return
  fi
}

function select_msg() {
  echo -e "${white}   [➔] ${1}"
}
function status_msg() {
  echo -e "\n${magenta}###### ${1}${white}"
}
function ok_msg() {
  echo -e "${green}[✓ OK] ${1}${white}"
}
function warn_msg() {
  echo -e "${yellow}>>>>>>> ${1}${white}"
}
function error_msg() {
  echo -e "${red}>>>>>>> ${1}${white}"
}
function abort_msg() {
  echo -e "${red}<<<<<<< ${1}${white}"
}
function title_msg() {
  echo -e "${cyan}${1}${white}"
}
function print_error() {
  [[ -z ${1} ]] && return

  echo -e "${red}"
  echo -e "#=======================================================#"
  echo -e " ${1} "
  echo -e "#=======================================================#"
  echo -e "${white}"
}
function print_confirm() {
  [[ -z ${1} ]] && return

  echo -e "${green}"
  echo -e "#=======================================================#"
  echo -e " ${1} "
  echo -e "#=======================================================#"
  echo -e "${white}"
}
function log_info() {
  local message="${1}" log="${LOGFILE}"
  echo -e "$(timestamp) [INFO]: ${message}" | tr -s " " >> "${log}"
}
function log_warning() {
  local message="${1}" log="${LOGFILE}"
  echo -e "$(timestamp) [WARN]: ${message}" | tr -s " " >> "${log}"
}
function log_error() {
  local message="${1}" log="${LOGFILE}"
  echo -e "$(timestamp) [ERR]: ${message}" | tr -s " " >> "${log}"
}
function timestamp() {
  date +"[%F %T]"
}
function report_status(){
    echo -e "\n\n###### $1"
}
clone_kiauh
status_msg "安装klipper！"
run_klipper_setup
status_msg "安装moonraker！"
moonraker_setup
status_msg "安装fluidd！"
install_fluidd
status_msg "安装mainsail！"
install_mainsail
status_msg "安装klipperscreen！"
klipperscreen_setup
status_msg "安装启动脚本！"
octoklipper_install
#rm -rf /home/print3D/kiauh
status_msg "安装完成！"
exit 0